package com.hwy.widget.utils;

import android.util.Log;

import androidx.annotation.MainThread;
import androidx.annotation.Nullable;

import java.util.ArrayList;
import java.util.List;

/**
 * ====================================
 * 作者: hewenyu
 * 日期: 2019/6/21 14:46
 * 说明: 日志输出工具类
 * ====================================
 */
public class LogUtil {

    // region ----------------- 初始化 -----------------

    // 类名
    private static String className;
    // 方法名
    private static String methodName;
    // 第几行
    private static int lineNumber;
    // 是否输出日志
    private static boolean mOutputLog = true;

    private static List<LogListener> logListenerList = new ArrayList<>();

    private LogUtil() {

    }

    @MainThread
    public static final void addLogListener(@Nullable LogListener listener) {
        if (listener != null && !logListenerList.contains(listener)) {
            logListenerList.add(listener);
        }
    }

    public static final void removeLogListener(@Nullable LogListener listener) {
        if (listener != null) {
            logListenerList.remove(listener);
        }
    }

    private static boolean isDebug() {
        return mOutputLog;
    }

    /**
     * 可以在项目的Application中初始化
     * LogUtil.init(BuildConfig.DEBUG);
     *
     * @param outputLog
     */
    public static void init(boolean outputLog) {
        mOutputLog = outputLog;
    }

    private static String createLog(String log) {
        StringBuffer buffer = new StringBuffer();
        buffer.append(methodName);
        buffer.append("(").append(className).append(":").append(lineNumber).append("): ");
        buffer.append(log);
        return buffer.toString();
    }

    /**
     * 获取方法名称
     *
     * @param elements
     */
    private static void getMethodNames(StackTraceElement[] elements) {
        className = elements[1].getFileName();
        methodName = elements[1].getMethodName();
        lineNumber = elements[1].getLineNumber();
    }

    // endregion ---------------------------------------------------

    public static void e(String message) {
        if (isDebug()) {
            getMethodNames((new Throwable()).getStackTrace());
            String msg = createLog(message);
            Log.e(className, msg);
            dispatchLog(Log.ERROR, msg);
        }
    }

    public static void e(Number message) {
        String msg = message == null ? "null" : String.valueOf(message);
        e(msg);
    }

    public static void w(String message) {
        if (isDebug()) {
            getMethodNames((new Throwable()).getStackTrace());
            String msg = createLog(message);
            Log.w(className, msg);
            dispatchLog(Log.WARN, msg);
        }
    }

    public static void w(Number message) {
        String msg = message == null ? "null" : String.valueOf(message);
        w(msg);
    }

    public static void i(String message) {
        if (isDebug()) {
            getMethodNames((new Throwable()).getStackTrace());
            String msg = createLog(message);
            Log.i(className, msg);
            dispatchLog(Log.INFO, msg);
        }
    }

    public static void i(Number message) {
        String msg = message == null ? "null" : String.valueOf(message);
        i(msg);
    }

    public static void d(String message) {
        if (isDebug()) {
            getMethodNames((new Throwable()).getStackTrace());
            String msg = createLog(message);
            Log.d(className, msg);
            dispatchLog(Log.DEBUG, msg);
        }
    }

    public static void d(Number message) {
        String msg = message == null ? "null" : String.valueOf(message);
        d(msg);
    }


    public static void v(String message) {
        if (isDebug()) {
            getMethodNames((new Throwable()).getStackTrace());
            String msg = createLog(message);
            Log.v(className, msg);
            dispatchLog(Log.VERBOSE, msg);
        }
    }

    public static void v(Number message) {
        String msg = message == null ? "null" : String.valueOf(message);
        v(msg);
    }

    private static void dispatchLog(int level, String msg) {
        for (LogListener listener : logListenerList) {
            listener.onLog(level, className, msg);
        }
    }

    public interface LogListener {

        /**
         * 日志输出回调
         *
         * @param level
         * @param className
         * @param msg
         */
        void onLog(int level, String className, String msg);

    }

}
